package types

import (
	"fmt"
	"strconv"
)

func ToFloat64(val interface{}) (float64, error) {

	boolVal, ok := val.(bool)
	if ok {
		if boolVal {
			return 1, nil
		}
		return 0, nil
	}

	byteVal, ok := val.(byte)
	if ok {
		return float64(byteVal), nil
	}

	uint8Val, ok := val.(uint8)
	if ok {
		return float64(uint8Val), nil
	}

	uint16Val, ok := val.(uint16)
	if ok {
		return float64(uint16Val), nil
	}

	uint32Val, ok := val.(uint32)
	if ok {
		return float64(uint32Val), nil
	}

	uint64Val, ok := val.(uint64)
	if ok {
		return float64(uint64Val), nil
	}

	intVal, ok := val.(int)
	if ok {
		return float64(intVal), nil
	}

	int8Val, ok := val.(int8)
	if ok {
		return float64(int8Val), nil
	}

	int16Val, ok := val.(int16)
	if ok {
		return float64(int16Val), nil
	}

	int32Val, ok := val.(int32)
	if ok {
		return float64(int32Val), nil
	}

	int64Val, ok := val.(int64)
	if ok {
		return float64(int64Val), nil
	}

	f64, ok := val.(float64)
	if ok {
		return f64, nil
	}

	f32Val, ok := val.(float32)
	if ok {
		return float64(f32Val), nil
	}

	str, ok := val.(string)
	if ok {
		parseIntVal, err := strconv.ParseInt(str, 10, 64)
		if err == nil {
			return float64(parseIntVal), nil
		}

		return strconv.ParseFloat(str, 64)
	}

	return 0, fmt.Errorf("%T 转成 float32 异常 \b", val)
}

func ToInt64(val interface{}) (int64, error) {

	boolVal, ok := val.(bool)
	if ok {
		if boolVal {
			return 1, nil
		}
		return 0, nil
	}

	byteVal, ok := val.(byte)
	if ok {
		return int64(byteVal), nil
	}

	uint8Val, ok := val.(uint8)
	if ok {
		return int64(uint8Val), nil
	}

	uint16Val, ok := val.(uint16)
	if ok {
		return int64(uint16Val), nil
	}

	uint32Val, ok := val.(uint32)
	if ok {
		return int64(uint32Val), nil
	}

	uint64Val, ok := val.(uint64)
	if ok {
		return int64(uint64Val), nil
	}

	intVal, ok := val.(int)
	if ok {
		return int64(intVal), nil
	}

	int8Val, ok := val.(int8)
	if ok {
		return int64(int8Val), nil
	}

	int16Val, ok := val.(int16)
	if ok {
		return int64(int16Val), nil
	}

	int32Val, ok := val.(int32)
	if ok {
		return int64(int32Val), nil
	}

	int64Val, ok := val.(int64)
	if ok {
		return int64Val, nil
	}

	f32Val, ok := val.(float32)
	if ok {
		return int64(f32Val), nil
	}

	f64, ok := val.(float64)
	if ok {
		return int64(f64), nil
	}

	str, ok := val.(string)
	if ok {
		parseIntVal, err := strconv.ParseInt(str, 10, 64)
		if err == nil {
			return parseIntVal, nil
		}

		floatVal, err2 := strconv.ParseFloat(str, 64)
		if err2 == nil {
			return int64(floatVal), nil
		}
		return 0, err
	}

	return 0, fmt.Errorf("%T 转成 int64 异常 \b", val)
}

func ToUint64(val interface{}) (uint64, error) {

	boolVal, ok := val.(bool)
	if ok {
		if boolVal {
			return 1, nil
		}
		return 0, nil
	}

	byteVal, ok := val.(byte)
	if ok {
		return uint64(byteVal), nil
	}

	uint8Val, ok := val.(uint8)
	if ok {
		return uint64(uint8Val), nil
	}

	uint16Val, ok := val.(uint16)
	if ok {
		return uint64(uint16Val), nil
	}

	uint32Val, ok := val.(uint32)
	if ok {
		return uint64(uint32Val), nil
	}

	uint64Val, ok := val.(uint64)
	if ok {
		return (uint64Val), nil
	}

	intVal, ok := val.(int)
	if ok {
		return uint64(intVal), nil
	}

	int8Val, ok := val.(int8)
	if ok {
		return uint64(int8Val), nil
	}

	int16Val, ok := val.(int16)
	if ok {
		return uint64(int16Val), nil
	}

	int32Val, ok := val.(int32)
	if ok {
		return uint64(int32Val), nil
	}

	int64Val, ok := val.(int64)
	if ok {
		return uint64(int64Val), nil
	}

	f32Val, ok := val.(float32)
	if ok {
		return uint64(f32Val), nil
	}

	f64, ok := val.(float64)
	if ok {
		return uint64(f64), nil
	}

	str, ok := val.(string)
	if ok {
		parseUintVal, err := strconv.ParseUint(str, 10, 64)
		if err == nil {
			return parseUintVal, nil
		}

		parseIntVal, err2 := strconv.ParseInt(str, 10, 64)
		if err2 == nil {
			return uint64(parseIntVal), nil
		}

		floatVal, err3 := strconv.ParseFloat(str, 64)
		if err3 == nil {
			return uint64(floatVal), nil
		}

		return 0, err
	}

	return 0, fmt.Errorf("%T 转成 uint64 异常 \b", val)
}

func ToString(val interface{}) string {
	str, ok := val.(string)
	if ok {
		return str
	}

	boolVal, ok := val.(bool)
	if ok {
		return fmt.Sprintf("%v", boolVal)
	}

	byteVal, ok := val.(byte)
	if ok {
		return fmt.Sprintf("%d", byteVal)
	}

	uint8Val, ok := val.(uint8)
	if ok {
		return fmt.Sprintf("%d", uint8Val)
	}

	uint16Val, ok := val.(uint16)
	if ok {
		return fmt.Sprintf("%d", uint16Val)
	}

	uint32Val, ok := val.(uint32)
	if ok {
		return fmt.Sprintf("%d", uint32Val)
	}

	uint64Val, ok := val.(uint64)
	if ok {
		return fmt.Sprintf("%d", uint64Val)
	}

	intVal, ok := val.(int)
	if ok {
		return fmt.Sprintf("%d", intVal)
	}

	int8Val, ok := val.(int8)
	if ok {
		return fmt.Sprintf("%d", int8Val)
	}

	int16Val, ok := val.(int16)
	if ok {
		return fmt.Sprintf("%d", int16Val)
	}

	int32Val, ok := val.(int32)
	if ok {
		return fmt.Sprintf("%d", int32Val)
	}

	int64Val, ok := val.(int64)
	if ok {
		return fmt.Sprintf("%d", int64Val)
	}

	f32Val, ok := val.(float32)
	if ok {
		return fmt.Sprintf("%.14g", f32Val)
	}

	f64, ok := val.(float64)
	if ok {
		return fmt.Sprintf("%.14g", f64)
	}

	return fmt.Sprintf("%v", val)
}
